Skip to content

fix: complete DOCX forward recovery - #237

Merged
stone16 merged 19 commits into
mainfrom
stone16/issue-204-docx-recovery
Aug 10, 2026
Merged

fix: complete DOCX forward recovery#237
stone16 merged 19 commits into
mainfrom
stone16/issue-204-docx-recovery

Conversation

@stone16

@stone16 stone16 commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Closes #204.

Summary

  • make DOCX recovery lossless-or-fail-closed across both the direct compiler and ContextEngine-owned runner, including w:fldSimple, w:smartTag, package grammar, content-type, relationship, fixed-object, and duplicate-ZIP-entry bypasses
  • scan duplicate archive entries by ZipInfo identity so a benign first entry cannot mask unsafe bytes in a later entry with the same filename
  • keep the RAGFlow vendored patch, UPSTREAM hash, aggregate SBOM, MODIFICATIONS record, and exclusions synchronized; PDF/OCR remains excluded
  • restore the WorkerLease expiry test to the exact pre-PR-fix: close RAGFlow document compiler registration #236 real-TTL behavior required by the forward-recovery instruction

Verification

  • focused direct/runner duplicate-entry regression and governance: 8 passed
  • compiler and registration surface: 165 passed
  • make lint
  • make typecheck
  • make test: 2,818 passed
  • make catalog: 135 passed; 15 invariants / 12 fixtures; 2 third-party registrations
  • fresh isolated checkout: the first unprepared make check stopped at action-build because dependencies had not been installed; make install then succeeded and the complete prepared rerun passed
  • fresh PostgreSQL integration: 753 passed, 4 deselected
  • fresh M0 security gate: 187/187 passed; 15/15 invariants; 12/12 fixtures; all 3 zero-valued hard oracles; 70/70 tenant tables under RLS; independent verdict m0SecurityDecision=pass
  • wheel, sdist, and npm shipped-artifact checks passed; container NOT_PRODUCED by maintainer decision
  • independent exact-head Spec review: PASS
  • independent exact-head Standards review: PASS after precedence adjudication; two non-blocking smells remain (vendored parser responsibility breadth and duplicated fallback scan shape)

Summary by CodeRabbit

  • Bug Fixes

    • Improved DOCX import validation for malformed, unsupported, or unsafe document content.
    • Added clearer handling for images, embedded objects, external links, thumbnails, merged cells, and nested tables.
    • Preserved document text, whitespace, and structural ordering more reliably.
    • Improved lease-expiration behavior during file import operations.
  • Quality Improvements

    • Expanded coverage for DOCX compatibility, malformed files, and edge cases to support more predictable imports.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@stone16, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 18 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9884bf49-751f-43d6-bfd4-e7bed10a93a9

📥 Commits

Reviewing files that changed from the base of the PR and between 1f8cbb2 and ea28e3a.

📒 Files selected for processing (6)
  • THIRD_PARTY_SBOM.cyclonedx.json
  • tests/unit/test_ragflow_document_compiler.py
  • third_party/ragflow/MODIFICATIONS.md
  • third_party/ragflow/UPSTREAM.toml
  • third_party/ragflow/deepdoc/parser/docx_parser.py
  • third_party/ragflow/patches/issue-204-docx-parser.patch
📝 Walkthrough

Walkthrough

The RAGFlow DOCX parser now performs strict OPC and OOXML validation, rejects unsupported or malformed content with typed errors, and extracts source-ordered blocks while preserving text. Tests add hostile package fixtures, seam comparisons, compiler safety checks, and updated registration metadata.

Changes

DOCX parser validation and extraction

Layer / File(s) Summary
Parser profile and output contract
third_party/ragflow/deepdoc/parser/docx_parser.py, third_party/ragflow/patches/issue-204-docx-parser.patch
The parser defines admitted DOCX structures and returns immutable RawDocxBlock records. Legacy image, classification, and DataFrame processing is removed.
Package and OOXML validation
third_party/ragflow/deepdoc/parser/docx_parser.py, third_party/ragflow/patches/issue-204-docx-parser.patch, tests/unit/test_ragflow_document_compiler.py
Archive paths, manifests, relationships, reachable parts, XML, thumbnails, text placement, and document structure are validated. Unsupported, malformed, visual, OLE, nested-table, and merged-cell content is rejected.
Block extraction and compiler seams
third_party/ragflow/deepdoc/parser/docx_parser.py, tests/unit/test_ragflow_document_compiler.py
Paragraph and table blocks retain source order and whitespace. Direct parser and runner compilation use paired outcomes. Runner profile, artifact, child-process, size, and import checks are covered.
Registration and vendored metadata
third_party/ragflow/MODIFICATIONS.md, third_party/ragflow/UPSTREAM.toml, THIRD_PARTY_SBOM.cyclonedx.json, tests/unit/test_third_party_ragflow_registration.py
Documentation, upstream metadata, SBOM data, and import-root allowlists reflect the updated parser.

Expired lease integration test

Layer / File(s) Summary
Lease expiry test setup
tests/integration/test_file_import_tracer.py
The test configures a one-second lease and waits 1.1 seconds before checking expired-lease behavior.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Compiler
  participant RAGFlowDocxParser
  participant OPCValidator
  participant PythonDocx
  Compiler->>RAGFlowDocxParser: provide DOCX bytes
  RAGFlowDocxParser->>OPCValidator: validate package and OOXML grammar
  OPCValidator-->>RAGFlowDocxParser: admit package or raise typed refusal
  RAGFlowDocxParser->>PythonDocx: construct document from validated bytes
  PythonDocx-->>RAGFlowDocxParser: provide document text and tables
  RAGFlowDocxParser-->>Compiler: return RawDocxBlock records
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The WorkerLease expiry test change is unrelated to DOCX parser registration or the requirements in [#204]. Move the WorkerLease test change to a separate pull request or link an issue that explicitly requires this behavior.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: completing DOCX forward recovery.
Linked Issues check ✅ Passed The parser patch removes lossy dependencies, validates DOCX structure, preserves block order and text, and adds deterministic refusal coverage required by [#204].
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch stone16/issue-204-docx-recovery

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
third_party/ragflow/deepdoc/parser/docx_parser.py (1)

925-931: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Hold one copy of the decompressed package, not two.

raw_package_members stores the full decompressed bytes of every member at line 927. Line 970 then reads each member again into package_members. In the common path no fallback runs, so the second copy is never used and peak memory is twice the decompressed package size.

The runner bounds compressed artifact bytes only. Decompressed size is unbounded, so the duplicate retention doubles the exposure of a high-ratio archive.

Read the raw bytes only when a fallback path is entered, or reuse the bytes already held in package_members. The same duplication exists in third_party/ragflow/patches/issue-204-docx-parser.patch lines 1049-1053; keep both in sync.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@third_party/ragflow/deepdoc/parser/docx_parser.py` around lines 925 - 931,
The DOCX parsing flow retains duplicate decompressed package bytes in
raw_package_members and package_members. Update the parser to read and retain
member bytes only when the fallback path requires them, or reuse the existing
package_members bytes, while preserving normal parsing behavior; apply the same
change to the corresponding issue-204-docx-parser.patch implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@third_party/ragflow/deepdoc/parser/docx_parser.py`:
- Around line 1209-1237: The early return in
_contains_unrepresented_package_structure incorrectly stops scanning after an
empty unrepresented package part. In
third_party/ragflow/deepdoc/parser/docx_parser.py lines 1209-1237, change the
conditional to return True only when the element has content, then continue to
inspect later parts; apply the identical change in
third_party/ragflow/patches/issue-204-docx-parser.patch lines 1368-1369 so the
patch record matches the vendored implementation.
- Around line 741-753: Update _resolved_relationship_target in
third_party/ragflow/deepdoc/parser/docx_parser.py to process each .. by removing
one parent segment and raise only when resolution escapes the package root;
relax the corresponding .. validation near line 798. Apply the identical change
in third_party/ragflow/patches/issue-204-docx-parser.patch at lines 846-847. In
tests/unit/test_ragflow_document_compiler.py lines 101-105, remove the
_save_docx rewrite of Target="../customXml/item1.xml" and add coverage compiling
unmodified document.save() bytes.

In `@third_party/ragflow/MODIFICATIONS.md`:
- Line 72: Update the wording in MODIFICATIONS.md so the compound modifier reads
“non-XML-related parts” instead of “non-XML related parts,” preserving the
surrounding text.

---

Nitpick comments:
In `@third_party/ragflow/deepdoc/parser/docx_parser.py`:
- Around line 925-931: The DOCX parsing flow retains duplicate decompressed
package bytes in raw_package_members and package_members. Update the parser to
read and retain member bytes only when the fallback path requires them, or reuse
the existing package_members bytes, while preserving normal parsing behavior;
apply the same change to the corresponding issue-204-docx-parser.patch
implementation.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 69af4a75-d6e9-4d07-bddc-db56619fa99f

📥 Commits

Reviewing files that changed from the base of the PR and between f4861c3 and 1f8cbb2.

📒 Files selected for processing (8)
  • THIRD_PARTY_SBOM.cyclonedx.json
  • tests/integration/test_file_import_tracer.py
  • tests/unit/test_ragflow_document_compiler.py
  • tests/unit/test_third_party_ragflow_registration.py
  • third_party/ragflow/MODIFICATIONS.md
  • third_party/ragflow/UPSTREAM.toml
  • third_party/ragflow/deepdoc/parser/docx_parser.py
  • third_party/ragflow/patches/issue-204-docx-parser.patch

Comment thread third_party/ragflow/deepdoc/parser/docx_parser.py
Comment thread third_party/ragflow/deepdoc/parser/docx_parser.py
Comment thread third_party/ragflow/MODIFICATIONS.md Outdated
@stone16

stone16 commented Aug 10, 2026

Copy link
Copy Markdown
Owner Author

Review follow-up: I also accept the decompressed-package memory finding from the CodeRabbit review summary. The fix owner will remove duplicate retained member-byte copies without weakening duplicate-entry identity checks, add bounded regression evidence where practical, and keep the vendored source, patch record, and registration hashes synchronized.

@stone16
stone16 merged commit c0a942c into main Aug 10, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Wave 3][ADR-0074] Approve RAGFlow DOCX + PDF-outline copy+patch registration

1 participant